/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.usecase.helper;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ExtensionPoint;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UseCase;

import com.cea.papyrus.core.helper.NodeHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.usecase.Activator;
import com.cea.papyrus.diagram.usecase.preference.UseCaseDiagramPreferenceConstants;
import com.cea.papyrus.diagraminterchange2.di2.Di2Factory;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Defines management of extension points.
 * 
 * @author Gilles Cannenterre
 * @since 9 oct. 06
 */
public class NodeExtensionPointHelper extends NodeHelper{
	
	/**
	 * The channel.
	 */
	private int channel = 203;
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#canCreateGraphElement(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	/**
	 * 
	 * 
	 * @param parent 
	 * 
	 * @return 
	 */
	@Override
	public boolean canCreateGraphElement(GraphElement parent) {
		Debug.debug(this,"canExecute(GraphNode)", channel);
		if (!(parent instanceof Diagram)) {//the parent must be a graphNode

			if(parent.getSemanticModel()==null){ // the parent must a Feature
				GraphElement gp=parent.getContainer();//look for GreatParent

				if (gp!=null){
					if (!(gp instanceof Diagram)) {//great parent is not a diagram
						if(gp.getSemanticModel()!=null){ //it is linked to an UML element
							Element elt= ((Uml1SemanticModelBridge)gp.getSemanticModel()).getElement();

							if ((elt instanceof UseCase) && (gp.getContained().get(0)==parent)){ //this is the first container of a classifier.
								return true;
							}
						}
					}
				}
			}
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#createUMLElement(java.lang.String, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param name 
	 * @param parent 
	 * 
	 * @return 
	 */
	@Override
	public Element createUMLElement(String name, Element parent) {
		Debug.debug(this,"createElement(String,Element)", channel);
		org.eclipse.uml2.uml.ExtensionPoint aExtensionPoint = null;
		if (parent instanceof UseCase){
			aExtensionPoint=UMLFactory.eINSTANCE.createExtensionPoint();
			aExtensionPoint.setName(name);
			((UseCase) parent).getExtensionPoints().add(aExtensionPoint);			
		}
		return aExtensionPoint;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#createGraphNode(org.eclipse.uml2.uml.Element, com.cea.papyrus.diagraminterchange2.di2.Diagram)
	 */
	/**
	 * 
	 * 
	 * @param umlElement 
	 * @param diagram 
	 * 
	 * @return 
	 */
	@Override
	public ArrayList createGraphNode(Element umlElement, Diagram diagram) {
		Debug.debug(this,"createGraphNode(Element,Diagram)++"+ umlElement.getClass()+ " dans "+diagram.getName(), channel);
		//look for graphNode of the umlElement parent
		ArrayList parentGraphNode=LookForElement.lookForGraphElement(umlElement.getOwner(), diagram, new ArrayList());
		Iterator it =parentGraphNode.iterator();
		ArrayList createdNode=new ArrayList();
		// this an array of graphNode linked to each Class node is 
	
		while(it.hasNext()){
			// Get current node
			GraphNode currentNode=(GraphNode)it.next();
	
			// Create a new node
			GraphNode graphNode=Di2Factory.eINSTANCE.createGraphNode();
			graphNode.setIsVisible(true);
			graphNode.setPosition(new Point(20, 20));
			graphNode.setSize(new Dimension(100,100));
			// Create UMLbridgee
			Uml1SemanticModelBridge semantic= Di2Factory.eINSTANCE.createUml1SemanticModelBridge();
			// Associate semantic with node
			graphNode.setSemanticModel(semantic);
			semantic.setElement(umlElement);
			
			setGraphElementPreferences(graphNode);
			
			// Add node to the right compartment (in this case the extension point compartment)
			((GraphNode)currentNode.getContained().get(0)).getContained().add(graphNode);
			createdNode.add(graphNode);
	
		}
		return createdNode;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#addUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean addUMLElement(Element element, Element umlParent) {
		if(umlParent instanceof UseCase) {
			return ((UseCase)umlParent).getExtensionPoints().add((ExtensionPoint)element);
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#canCreateUMLElement(org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean canCreateUMLElement(Element umlParent) {
		if(umlParent instanceof UseCase) {
			return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#removeUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean removeUMLElement(Element element, Element umlParent) {
		if(umlParent instanceof UseCase) {
			return ((UseCase)umlParent).getExtensionPoints().remove(element);
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#setGraphElementPreferences(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	/**
	 * 
	 * 
	 * @param graphElement 
	 */
	@Override
	public void setGraphElementPreferences(GraphElement graphElement) {	
		// Get the preference store
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		
		// Set colors and font
		graphElement.setBackgroundColor(UseCaseDiagramPreferenceConstants.getPreferenceExtensionPointBackgroundColor(store));
		graphElement.setBorderColor(UseCaseDiagramPreferenceConstants.getPreferenceExtensionPointBorderColor(store));
		graphElement.setFontColor(UseCaseDiagramPreferenceConstants.getPreferenceExtensionPointFontColor(store));
		FontData[] fontdata = UseCaseDiagramPreferenceConstants.getPreferenceExtensionPointFont(store);
		if (fontdata.length>0){
			graphElement.setFontFamily(fontdata[0].getName());
			graphElement.setFontSize(fontdata[0].getHeight());
		}
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.NodeFactory#getBaseString()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public String getBaseString() {
		return "ExtensionPoint_"; //$NON-NLS-1$
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.NodeHelper#getNewUMLElementName(org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public String getNewUMLElementName(Element umlParent) {
		String name = ""; //$NON-NLS-1$
	
		// i <10000: avoid infinite loops
		for(int i=0; i< 10001; i++ ) {
			name = getBaseString()+i;
			if(null == ((UseCase)umlParent).getExtensionPoint(name)) {
				return name;
			}
		}
		return getBaseString()+"X"; //$NON-NLS-1$
	}
}